home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 2.iso / dist / fw_glimpse.idb / usr / freeware / src / glimpse-3.0 / compress / quick.c.z / quick.c
C/C++ Source or Header  |  1997-09-09  |  8KB  |  233 lines

  1. /* Copyright (c) 1994 Burra Gopal, Udi Manber.  All Rights Reserved. */
  2.  
  3. /*
  4.  * quick.c:    Used to search for a pattern in a compressed file.
  5.  *
  6.  * Algorithm: if the file (or stdin) is a compressed file, then:
  7.  * +  a. Read in the hash-table-index file.
  8.  * +  b. For each page in which the words of the pattern can be found:
  9.  *     build the hash-table using the words in exactly those pages.
  10.  * +  c. Now, call compress with the given pattern.
  11.  *
  12.  * +  d. Call the normal search routines with the compressed pattern on
  13.  *     the input file.
  14.  * +  e. If the option is to count number of matches, just exit.
  15.  *     Otherwise we have to modify the r_output/output routines:
  16.  *
  17.  * +  f. Read in the string-table-index file.
  18.  * +  g. For each page in which the word numbers of the input file can
  19.  *     be found: build the string-table using the words in exactly
  20.  *     those pages.
  21.  * +  h. Call uncompress with the input file line to be output and
  22.  *     output THIS line instead of the original matched line.
  23.  *
  24.  * Part of this will be in agrep and part of this here.
  25.  */
  26.  
  27. #include "defs.h"
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30.  
  31. /*
  32.  * The quick-functions can be called multiple number of times --
  33.  * they however open the hash, string and freq files only once.
  34.  */
  35.  
  36. hash_entry *compress_hash_table[HASH_TABLE_SIZE];    /* used for compress: assume it is zeroed by C */
  37. char    loaded_hash_table[HASH_FILE_BLOCKS];        /* bit mask of loaded pages in hash-table: store chars since just 4K: speed is most imp. */
  38. char    *hashindexbuf;
  39. int    hashindexsize;
  40.  
  41. /* returns length of compressed pattern after filling up the compressed pattern in the user-supplied newpattern buffer */
  42. int
  43. quick_tcompress(freq_file, hash_file, pattern, len, newpattern, maxnewlen, flags)
  44.     char    *freq_file;
  45.     char    *hash_file;
  46.     CHAR    *pattern;
  47.     int    len;
  48.     void    *newpattern;    /* can be FILE* or CHAR* */
  49.     int    *maxnewlen;
  50.     int    flags;
  51. {
  52.     static FILE    *hashfp = NULL, *hashindexfp = NULL;
  53.     static char    old_freq_file[MAX_LINE_LEN] = "", old_hash_file[MAX_LINE_LEN] = "";
  54.     static int    blocksize;
  55.     int        newlen;
  56.  
  57.     if ((hashfp == NULL) || (strcmp(freq_file, old_freq_file)) || (strcmp(hash_file, old_hash_file)))
  58.     {    /* Have to do some initializations */
  59.         char    s[256];
  60.         struct stat statbuf;
  61.  
  62.         if (hashfp != NULL) {
  63.             uninitialize_tcompress();
  64.             fclose(hashfp);
  65.             hashfp = NULL;
  66.         }
  67.         else memset(loaded_hash_table, '\0', HASH_FILE_BLOCKS);
  68.         if (!initialize_common(freq_file, flags)) return 0;    /* don't call initialize_tcompress since that will load the FULL hash table */
  69.  
  70.         if ((hashfp = fopen(hash_file, "r")) == NULL) {
  71.             if (flags & TC_ERRORMSGS) {
  72.                 fprintf(stderr, "cannot open cast-dictionary file: %s\n", hash_file);
  73.                 fprintf(stderr, "(use -H to give a dictionary-dir or run 'buildcast' to make a dictionary)\n");
  74.             }
  75.             return 0;
  76.         }
  77.  
  78.         sprintf(s, "%s.index", hash_file);
  79.         if ((hashindexfp = fopen(s, "r")) == NULL) {
  80.             if (flags & TC_ERRORMSGS)
  81.                 fprintf(stderr, "cannot open for reading: %s\n", s);
  82.             fclose(hashfp);
  83.             hashfp = NULL;
  84.             return 0;
  85.         }
  86.         blocksize = 0;
  87.         fscanf(hashindexfp, "%d\n", &blocksize);
  88.         if (blocksize == 0) blocksize = DEF_BLOCKSIZE;
  89.  
  90.         if (fstat(fileno(hashindexfp), &statbuf) == -1) {
  91.             fprintf(stderr, "error in quick_tcompress/fstat on '%s.index'\n", hash_file);
  92.             fclose(hashfp);
  93.             hashfp = NULL;
  94.             fclose(hashindexfp);
  95.             hashindexfp = NULL;
  96.             return 0;
  97.         }
  98.  
  99.         if ((hashindexbuf = (char *)malloc(statbuf.st_size + 1)) == NULL) {
  100.             if (flags & TC_ERRORMSGS)
  101.                 fprintf(stderr, "quick_tcompress: malloc failure!\n");
  102.             fclose(hashfp);
  103.             hashfp = NULL;
  104.             fclose(hashindexfp);
  105.             hashindexfp = NULL;
  106.             return 0;
  107.         }
  108.  
  109.         if ((hashindexsize = fread(hashindexbuf, 1, statbuf.st_size, hashindexfp)) == -1) {
  110.             fprintf(stderr, "error in quick_tcompress/fread on '%s.index'\n", hash_file);
  111.             fclose(hashfp);
  112.             hashfp = NULL;
  113.             fclose(hashindexfp);
  114.             hashindexfp = NULL;
  115.             return 0;
  116.         }
  117.         hashindexsize ++;    /* st_size - bytes used up for blocksize in file + 1 <= st_size */
  118.         hashindexbuf[hashindexsize] = '\0';
  119.         fclose(hashindexfp);
  120.  
  121.         strcpy(old_freq_file, freq_file);
  122.         strcpy(old_hash_file, hash_file);
  123.     }
  124.     else rewind(hashfp);    /* Don't do it first time */
  125.  
  126.     if (pattern[len-1] == '\0') len--;
  127.     build_partial_hash(compress_hash_table, hashfp, hashindexbuf, hashindexsize, pattern, len, blocksize, loaded_hash_table);
  128.     newlen = tcompress(pattern, len, newpattern, maxnewlen, flags);
  129. #if    0
  130.     printf("quick_tcompress: pat=%s len=%d newlen=%d newpat=", pattern, len, newlen);
  131.     for (i=0; i<newlen; i++) printf("%d ", newpattern[i]);
  132.     printf("\n");
  133. #endif    /*0*/
  134.     return newlen;
  135. }
  136.  
  137. char    *compress_string_table[DEF_MAX_WORDS]; /*[MAX_WORD_LEN+2]; */
  138. char    loaded_string_table[STRING_FILE_BLOCKS];        /* bit mask of loaded pages in string-table: store chars since just 4K: speed is most imp. */
  139. char    *stringindexbuf;
  140. int    stringindexsize;
  141.  
  142. /* returns length of uncompressed pattern after filling up the uncompressed pattern in the user-supplied newpattern buffer */
  143. int
  144. quick_tuncompress(freq_file, string_file, pattern, len, newpattern, maxnewlen, flags)
  145.     char    *string_file;
  146.     char    *freq_file;
  147.     CHAR    *pattern;
  148.     int    len;
  149.     void    *newpattern;    /* can be FILE* or CHAR* */
  150.     int    *maxnewlen;
  151.     int    flags;
  152. {
  153.     static FILE    *stringfp = NULL, *stringindexfp = NULL;
  154.     static char    old_freq_file[MAX_LINE_LEN] = "", old_string_file[MAX_LINE_LEN] = "";
  155.     static int    blocksize;
  156.     int        newlen;
  157.     int        dummy;
  158.  
  159.     if ((stringfp == NULL) || (strcmp(freq_file, old_freq_file)) || (strcmp(string_file, old_string_file)))
  160.     {    /* Have to do some initializations */
  161.         char    s[256];
  162.         struct stat statbuf;
  163.  
  164.         if (stringfp != NULL) {
  165.             uninitialize_tuncompress();
  166.             fclose(stringfp);
  167.             stringfp = NULL;
  168.         }
  169.         else memset(loaded_string_table, '\0', STRING_FILE_BLOCKS);
  170.         if (!initialize_common(freq_file, flags)) return 0;    /* don't call initialize_tuncompress since that will load the FULL string table */
  171.  
  172.         if ((stringfp = fopen(string_file, "r")) == NULL) {
  173.             if (flags & TC_ERRORMSGS) {
  174.                 fprintf(stderr, "cannot open cast-dictionary file: %s\n", string_file);
  175.                 fprintf(stderr, "(use -H to give a dictionary-dir or run 'buildcast' to make a dictionary)\n");
  176.             }
  177.             return 0;
  178.         }
  179.  
  180.         sprintf(s, "%s.index", string_file);
  181.         if ((stringindexfp = fopen(s, "r")) == NULL) {
  182.             if (flags & TC_ERRORMSGS)
  183.                 fprintf(stderr, "cannot open for reading: %s\n", s);
  184.             fclose(stringfp);
  185.             stringfp = NULL;
  186.             return 0;
  187.         }
  188.         blocksize = 0;
  189.         fscanf(stringindexfp, "%d\n", &blocksize);
  190.         if (blocksize == 0) blocksize = DEF_BLOCKSIZE;
  191.  
  192.         if (fstat(fileno(stringindexfp), &statbuf) == -1) {
  193.             fprintf(stderr, "error in quick_tuncompress/fstat on '%s.index'\n", string_file);
  194.             fclose(stringfp);
  195.             stringfp = NULL;
  196.             fclose(stringindexfp);
  197.             stringindexfp = NULL;
  198.             return 0;
  199.         }
  200.  
  201.         if ((stringindexbuf = (char *)malloc(statbuf.st_size + 1)) == NULL) {
  202.             if (flags & TC_ERRORMSGS)
  203.                 fprintf(stderr, "quick_tuncompress: malloc failure!\n");
  204.             fclose(stringfp);
  205.             stringfp = NULL;
  206.             fclose(stringindexfp);
  207.             stringindexfp = NULL;
  208.             return 0;
  209.         }
  210.  
  211.         stringindexsize = 0;
  212.         while(fscanf(stringindexfp, "%d\n", &dummy) == 1) {
  213.             *((unsigned short *)(stringindexbuf+stringindexsize)) = (unsigned short)dummy;
  214.             stringindexsize+=sizeof(unsigned short);
  215.         }
  216.         fclose(stringindexfp);
  217.  
  218.         strcpy(old_freq_file, freq_file);
  219.         strcpy(old_string_file, string_file);
  220.     }
  221.     else rewind(stringfp);
  222.  
  223.     build_partial_string(compress_string_table, stringfp, stringindexbuf, stringindexsize, pattern, len, blocksize, loaded_string_table);
  224.     newlen = tuncompress(pattern, len, newpattern, maxnewlen, flags);
  225. #if    0
  226.     printf("quick_tuncompress: len=%d newlen=%d newpat=%s pat=", len, newlen, newpattern);
  227.     for (i=0; i<len; i++) printf("%d ", pattern[i]);
  228.     printf("\n");
  229. #endif    /*0*/
  230.     return newlen;
  231. }
  232.  
  233.